import sys
import traceback
from pathlib import Path
import shutil
from typing import Union

from jinja2 import Environment, FileSystemLoader


def to_camel_case(s: str):
    return ''.join([t.title() for t in s.split('_')])


def name(l: list):
    return [d[0] for d in l]


class TemplateHandler:
    template_paths = [Path('.').parent.joinpath('templates').as_posix(), ]

    @classmethod
    def add_template_path(cls, paths: Union[str, list, tuple]):
        if type(paths) is str and paths not in cls.template_paths:
            cls.template_paths.insert(0, paths)
        elif type(paths) is list or type(paths) is tuple:
            cls.template_paths = [p for p in paths if p not in cls.template_paths] \
                                 + cls.template_paths

    @classmethod
    def get_loader(cls):
        # return ChoiceLoader([FileSystemLoader(cls.template_paths),
        #                      PackageLoader('dpgtools')])
        return FileSystemLoader(cls.template_paths)

    def gen_file_from_templates(self, temp_file, dst_file, **context):
        """
        TemplateHandler的核心api，转化模板文件
        :param temp_file:
        :param dst_file:
        :param data:
        :return:
        """
        env = Environment(loader=self.get_loader())
        env.filters['camel_case'] = to_camel_case
        env.filters['name'] = name
        template = env.get_template(temp_file)
        context.update({
            'py_exe': sys.executable,
            'py_path': sys.exec_prefix
        })
        with open(dst_file, 'w', encoding='utf-8') as f:
            f.write(template.render(**context))

    def gen_module_by_templates_dir(self, src_dir, dst_dir, **context):

        if src_dir and dst_dir:
            src_dir = Path(src_dir)
            if not src_dir.is_dir():
                return
            if src_dir not in self.template_paths:
                self.add_template_path(src_dir.as_posix())
            dst_dir = Path(dst_dir)
            if not dst_dir.exists():
                dst_dir.mkdir(exist_ok=True)

            for fp in src_dir.iterdir():
                if fp.name.startswith('_'):
                    continue
                try:
                    if fp.is_file():
                        if fp.suffix == '.jinja2':
                            dst_file = dst_dir.joinpath(fp.name[:-7])
                            self.gen_file_from_templates(
                                fp.name,
                                dst_file.absolute().resolve().as_posix(),
                                **context
                            )
                        else:
                            dst_file = dst_dir.joinpath(fp.name)
                            shutil.copy(fp, dst_file)
                    elif fp.is_dir():
                        self.gen_module_by_templates_dir(fp.absolute().as_posix(), dst_dir.joinpath(fp.name).as_posix(),
                                                         **context)
                except Exception:
                    traceback.print_exc()
                    continue


templates_handler = TemplateHandler()
